package com.ferry.transport.netty.server;

import com.ferry.registry.domain.registry.RegistryMetaData;
import com.ferry.registry.domain.registry.RegistryType;
import com.ferry.registry.service.IRegistryService;
import com.ferry.registry.zk.ZkRegistryServiceImpl;
import com.ferry.transport.api.Directory;
import com.ferry.transport.api.config.ChildConfig;
import com.ferry.transport.api.config.ParentConfig;
import com.ferry.transport.netty.provider.DefaultNettyTcpAcceptor;
import com.ferry.transport.netty.provider.DefaultProviderProcessor;
import com.ferry.transport.netty.provider.ServiceWrapper;
import com.ferry.transport.netty.provider.TcpAcceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by daiyong
 */
public class DefaultProviderServer implements ProviderServer{

	private static final Logger logger = LoggerFactory.getLogger(DefaultProviderServer.class);

	private volatile boolean started = false;

	private String registryAddress;
	private int port;
	private List<RegistryMetaData> registryMetaDatas = new ArrayList<>();
	private ParentConfig parentConfig;
	private ChildConfig childConfig;


	//服务监听器
	private TcpAcceptor tcpAcceptor;

	//注册中心
	private IRegistryService registryService;

	private DefaultServiceProviderContainer defaultServiceProviderContainer = new DefaultServiceProviderContainer();

	public DefaultProviderServer() {

	}

	@Override
	public synchronized void start() {
		if (started) {
			logger.info("DefaultProviderServer has started...");
		} else {
			logger.info("DefaultProviderServer start ...");

			//启动监听
			tcpAcceptor = new DefaultNettyTcpAcceptor(port, 20);
			tcpAcceptor.withProcessor(new DefaultProviderProcessor(defaultServiceProviderContainer));
			ParentConfig parentConfig = tcpAcceptor.parentConfig();
			parentConfig = parentConfig;

			ChildConfig childConfig = tcpAcceptor.childConfig();
			childConfig = childConfig;

			try {
				tcpAcceptor.start(false);
				logger.info("server start success!");
			} catch (InterruptedException e) {
				logger.error("tcpAcceptor start exception", e);
				throw new RuntimeException(e);
			}
			started = true;
			//启动监听结束

			//发布服务 开始
			connectRegistry(registryAddress);
			for (RegistryMetaData registryMetaData : registryMetaDatas) {
				publish(registryMetaData);
				logger.info("服务注册成功:{}", registryMetaData);
			}
		}

	}

	@Override
	public void publish(List<RegistryMetaData> registryMetaDatas) {
		for (RegistryMetaData registryMetaData : registryMetaDatas) {
			publish(registryMetaData);
		}
	}

	@Override
	public void publish(RegistryMetaData registryMetaData) {
		registryService.registry(registryMetaData);
		ServiceWrapper wrapper = new ServiceWrapper();
		wrapper.setMetadata(registryMetaData.getServiceMetaData());
		wrapper.setServiceProvider(registryMetaData.getProvider());
		wrapper.setExtensions(registryMetaData.getExtensions());
		defaultServiceProviderContainer.registerService(registryMetaData.getServiceMetaData().directoryString(), wrapper);
	}

	@Override
	public void shutdownGracefully() {

	}

	@Override
	public ServiceWrapper lookup(Directory directory) {
		return null;
	}

	private void connectRegistry(String registryAddress) {
		//默认只有zk注册中心，以后可能回增加etcd
		RegistryType registryType = getRegistryType(registryAddress);
		if (null == registryType) {
			throw new IllegalArgumentException("不支持当前类型注册中心");
		}
		if (registryType == RegistryType.ZOOKEEPER) {
			registryService = buildZkRegistryService(registryAddress);
		}
	}

	private RegistryType getRegistryType(String registryAddress) {

		String[] split = registryAddress.split("//");
		String protocol = split[0].replace(":", "");

		return RegistryType.getRegistryTypeByProtocol(protocol);
	}

	private IRegistryService buildZkRegistryService(String registryAddress) {
		IRegistryService registryService = new ZkRegistryServiceImpl();
		registryService.connect(registryAddress.split("//")[1]);
		return registryService;
	}

	public void setRegistryAddress(String registryAddress) {
		this.registryAddress = registryAddress;
	}

	public void setPort(int port) {
		this.port = port;
	}

	public void setRegistryMetaDatas(List<RegistryMetaData> registryMetaDatas) {
		this.registryMetaDatas = registryMetaDatas;
	}

	public void setParentConfig(ParentConfig parentConfig) {
		this.parentConfig = parentConfig;
	}

	public void setChildConfig(ChildConfig childConfig) {
		this.childConfig = childConfig;
	}
}
